package org.example.com.pattern.action.command

import java.awt.datatransfer.Clipboard
import java.util.LinkedList
import java.util.Stack

/**
 * 行为型模式-命令模式
 */

/**
 * 命令基类会为所有具体命令定义通用接口
 */
abstract class Command(val app: Application, val editor: Editor) {
    protected var backup: String? = null
    fun saveBackup() {
        backup = editor.text
    }

    fun undo() {
        editor.text = backup
    }

    abstract fun execute(): Boolean
}

class CopyCommand(app: Application, editor: Editor) : Command(app, editor) {
    override fun execute(): Boolean {
        app.clipboard = editor.getSelection()
        return false
    }
}

class CutCommand(app: Application, editor: Editor) : Command(app, editor) {
    override fun execute(): Boolean {
        saveBackup()
        app.clipboard = editor.getSelection()
        editor.deleteSelection()
        return true
    }
}


class PastCommand(app: Application, editor: Editor) : Command(app, editor) {
    override fun execute(): Boolean {
        saveBackup()
        editor.replaceSelection(app.clipboard ?: "")
        return true
    }
}

class UndoCommand(app: Application, editor: Editor) : Command(app, editor) {
    override fun execute(): Boolean {
        app.undo()
        return false
    }
}

class CommandHistory {
    private var history = LinkedList<Command>()
    fun push(command: Command) {
        history.push(command)
    }

    fun pop(): Command? {
        return history.pop()
    }
}

class Editor {
    var text: String? = null
    fun getSelection(): String {
        return ""
    }

    fun deleteSelection() {

    }

    fun replaceSelection(text: String) {

    }

}

class Application {
    var clipboard: String? = null
    private val editors = LinkedList<Editor>()
    private var activeEditor: Editor? = null
    private val history = CommandHistory()

    fun executeCommand(command: Command){
        if (command.execute()){
            history.push(command)
        }
    }

    fun undo() {
        val command = history.pop()
        command?.undo()
    }
}